﻿using System.Collections.Generic;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using ESoft.AspNetCore.Login;
using ESoft.Extensions;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace ESoft.AspNetCore.Authentication
{
    /// <summary>
    /// 参数登录校验
    /// </summary>
    public class HeaderAuthenticationHandler : AuthenticationHandler<HeaderAuthenticationOptions>
    {
        private readonly ISessionService<IApplicationSession> _currentUser;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public HeaderAuthenticationHandler(IOptionsMonitor<HeaderAuthenticationOptions> options, ILoggerFactory logger,
            UrlEncoder encoder, ISystemClock clock, ISessionService<IApplicationSession> currentUser, IHttpContextAccessor httpContextAccessor)
            : base(options, logger, encoder, clock)
        {
            _currentUser = currentUser;
            _httpContextAccessor = httpContextAccessor;
        }

        protected override Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            string authorize = _httpContextAccessor.HttpContext.Request.Headers["authorization"];
            if (string.IsNullOrWhiteSpace(authorize) || !authorize.StartsWith("Bearer "))
            {
                return Task.FromResult(AuthenticateResult.NoResult());
            }

            var token = authorize.Split(" ")[1];
            var loginUser = _currentUser.Refresh(token);
            if (loginUser.IsNull())
            {
                return Task.FromResult(AuthenticateResult.NoResult());
            }

            var claims = new List<Claim>()
            {
                new Claim(ClaimTypes.NameIdentifier, loginUser.UserId)
            };

            var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Scheme.Name));
            var ticket = new AuthenticationTicket(
                principal,
                Scheme.Name
            );

            return Task.FromResult(AuthenticateResult.Success(ticket));
        }
    }
}
